﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Base.DAL;
using System.Text.RegularExpressions;
using System.Collections.Concurrent;

namespace Base.BLL
{
    /// <summary>
    /// 综采数据处理器
    /// </summary>
    class DataParser4ZC : IDataParser
    {
        /// <summary>
        /// 存储时间记录列表，记录每个工作面上次存储时间
        /// </summary>
        private Dictionary<int, DateTime> lastStorageT = new Dictionary<int, DateTime>();
        /// <summary>
        /// 参数配置
        /// </summary>
        static IEnumerable<View_ZC_INI> inis= Db.Query<View_ZC_INI>();

        /// <summary>
        /// 数据有效性验证的正则表达式
        /// </summary>
        public static readonly string pattern = @"(\d{3})Z(\d{3})(\d{3})(\d{3})";

        /// <summary>
        /// 从字符串中解析数据，并更新最新数据缓存
        /// </summary>
        /// <param name="cqbh">测区编号</param>
        /// <param name="data">数据内容</param>   
        /// <param name="dt">解析时刻</param>
        /// <param name="cache">当前最新数据缓存</param>
        /// <returns>转换后的数据，转换失败为null</returns>
        public object Parse(int cqbh, string data, DateTime dt, IEnumerable<IEntity> cache)
        {
            GroupCollection matches = Regex.Match(data, pattern).Groups;
            if (matches.Count == 1)
            {
                return null;
            }
            int bh = int.Parse(matches[1].Value);
            View_ZC_INI ini;
            if (!ConfigService.FindWarn<View_ZC_INI>(cqbh, bh, out ini))
            {
                return null;
            }
            //被禁用或不存在
            if (ini == null)
            {
                return null;
            }
            ZCSJB d = new ZCSJB
            {
                CQBH = cqbh,
                ZDATETIME = dt,
                ZBH = bh,
                P1 = ini.FIRSTGJ == 0 ? 0 : double.Parse((double.Parse(matches[2].Value) /4.25).ToString("f1")),
                P2 = ini.SECONDGJ == 0 ? 0 : double.Parse((double.Parse(matches[3].Value) / 4.25).ToString("f1")),
                P3 = ini.THIRDGJ==0?0: double.Parse((double.Parse(matches[4].Value) / 4.25).ToString("f1")),
            };
            //大于60MPa记为59.9MPa
            d.P1 = d.P1 >= 60 ? 59.9 : d.P1;
            d.P2 = d.P2 >= 60 ? 59.9 : d.P2;
            d.P3 = d.P3 >= 60 ? 59.9 : d.P3;
            //计算是否报警
            //d.SFBJ = d.P1 < ini.YLXX || d.P1 > ini.YLSX ||
            //    d.P2 < ini.YLXX || d.P2 > ini.YLSX ||
            //    d.P3 < ini.YLXX || d.P3 > ini.YLSX;
            d.SFBJ = d.P1 > ini.YLBJZ || d.P2 > ini.YLBJZ || 
                (ini.THIRDGJ>0 && d.P3 > ini.YLBJZ);
            foreach (var _c in cache)
            {
                View_ZC_Active c = _c as View_ZC_Active;
                if (c == null) break;
                if (c.CQBH == d.CQBH && c.ZBH == d.ZBH)
                {
                    c.ZDATETIME = d.ZDATETIME;
                    c.P1 = d.P1;
                    c.P2 = d.P2;
                    c.P3 = d.P3;
                    c.SFBJ = d.SFBJ;
                    break;
                }
            }
            return d;
        }
        /// <summary>
        /// 获取正则验证字符串
        /// </summary>
        /// <returns>正则验证字符串</returns>
        public string RegexPattern()
        {
            return pattern;
        }
        /// <summary>
        /// 存储综采数据
        /// </summary>
        /// <param name="data">综采数据</param>
        public void Storage(ConcurrentQueue<IEntity> data)
        {
            if (data.IsEmpty)
            {
                return;
            }
            //插入数据
            List<IEntity> toSave = data.ToList();
            List<int> toInsertID = new List<int>();
            List<IEntity> toInsert = new List<IEntity>();
            DateTime now = DateTime.Now;
            int csKey = 0;//参数key
            bool needInsert = false;
            foreach (var ini in inis)
            {
                //新的工作面
                if(csKey!= ini.GZMBH)
                {
                    csKey = ini.GZMBH;
                    int span = int.Parse(ini.SJJLZQ);
                    if (!lastStorageT.ContainsKey(csKey))
                    {
                        needInsert = true;
                    }
                    else
                    {
                        needInsert = (now - lastStorageT[csKey]).TotalMinutes >= span;
                    }
                    if(needInsert)
                    {
                        lastStorageT[csKey] = now;
                    }
                }
                if(needInsert)
                {
                    toInsertID.Add(ini.BH);
                }
            }
            for (int i = toSave.Count - 1; i >= 0; i--)
            {
                ZCSJB d = (ZCSJB)toSave[i];
                int id= d.ZBH;
                if (toInsertID.Contains(id))
                {
                    toInsert.Add(d);
                    toInsertID.Remove(id);
                }
            }
            Db.Insert(toInsert);
            #region 旧方式，弃用
            /*
            //更新临时表，时间替换为存储时间
            ZCSJB first = (ZCSJB)toSave[0];
            string sql = @"SELECT ID,CQBH,ZBH,P1,P2,P3,Q1,Q2,S,SFBJ,FIELD1,FIELD2,FIELD3,FIELD4,ZDATETIME 
                            FROM ZCSJB_TEMP
                            WHERE ZDATETIME=(SELECT MAX(ZDATETIME) FROM ZCSJB_TEMP WHERE CQBH=" + first.CQBH + ")";
            List<ZCSJB> toAdd = new List<ZCSJB>();
            List<ZCSJB> toUpdate = new List<ZCSJB>();
            //仅更新数据池中较新的数据
            List<string> added = new List<string>();
            for (int i = toSave.Count - 1; i >= 0;i--)
            {
                ZCSJB d = (ZCSJB)toSave[i];
                string addKey = d.CQBH + "#" + d.ZBH;
                if (added.Contains(addKey))
                {
                    continue;
                }
                added.Add(addKey);
                bool isUpdate = false;
                foreach (var cur in Db.Query<ZCSJB_TEMP>(sql))
                {
                    if (d.CQBH == cur.CQBH && d.ZBH == cur.ZBH)
                    {
                        d.ID = cur.ID;
                        toUpdate.Add(d);
                        isUpdate = true;
                        break;
                    }
                }
                if (!isUpdate)
                {
                    toAdd.Add(d);
                }
            }
            Db.Execute<ZCSJB>(Db.SqlUpdate(new ZCSJB_TEMP()), toUpdate);
            Db.Execute<ZCSJB>(Db.SqlInsert(new ZCSJB_TEMP()), toAdd);
            */
            #endregion
            //清空数据缓冲池            
            int curCunt = data.Count;
            IEntity toDel = null;
            while (curCunt-- > 0 && !data.IsEmpty)
            {
                if (data.TryDequeue(out toDel))
                {
                    //DataParseService.Parsers[DATA_TYPE.ZCSJ].Storage(data);
                }
            }
        }

        /// <summary>
        /// 存储综采当前数据
        /// </summary>
        /// <param name="data">综采数据</param>
        public void StorageCur(IEnumerable<IEntity> data)
        {
            if (data.IsEmpty()) return;
            List<IEntity> toSave = data.ToList();
            //更新临时表，时间替换为存储时间
            var curs = Db.Query<ZCSJB_TEMP>();
            List<ZCSJB_TEMP> toAdd = new List<ZCSJB_TEMP>();
            List<ZCSJB_TEMP> toUpdate = new List<ZCSJB_TEMP>();
            //仅更新数据池中较新的数据
            List<string> added = new List<string>();
            for (int i = toSave.Count - 1; i >= 0;i--)
            {
                View_ZC_Active d = (View_ZC_Active)toSave[i];
                if (d.ZDATETIME == DateTime.MinValue) continue;
                string addKey = d.CQBH + "#" + d.ZBH;
                if (added.Contains(addKey))
                {
                    continue;
                }
                added.Add(addKey);
                bool isUpdate = false;
                foreach (var cur in curs)
                {
                    if (d.CQBH == cur.CQBH && d.ZBH == cur.ZBH)
                    {
                        //d.ID = cur.ID;
                        Db.Cpy(d, cur);
                        toUpdate.Add(cur);
                        isUpdate = true;
                        break;
                    }
                }
                if (!isUpdate)
                {
                    ZCSJB_TEMP add = new ZCSJB_TEMP();
                    Db.Cpy(d, add);
                    toAdd.Add(add);
                }
            }
            Db.Update<ZCSJB_TEMP>(toUpdate);
            Db.Insert<ZCSJB_TEMP>(toAdd);
        }
        /// <summary>
        /// 获取最新一条数据时间
        /// </summary>
        /// <param name="cqbh">测区编号</param>
        /// <param name="hSpan">加权时长</param>
        /// <returns></returns>
        //public DateTime LastDateTime(int cqbh, int hSpan)
        //{
        //    string sql = @"SELECT MAX(ZDATETIME) FROM ZCSJB_JQ" + hSpan+" WHERE CQBH="+cqbh;
        //    return Db.Query<DateTime>(sql).FirstOrDefault();
        //}

        /// <summary>
        /// 数据计算，进行加权平均操作
        /// </summary>
        /// <param name="tStart">计算起始时刻</param>
        /// <param name="tEnd">计算结束时刻</param>
        /// <param name="hSpan">加权平均时长，取2，4，8，12，24</param>
        public void Calc(DateTime tStart,DateTime tEnd, int hSpan)
        {
            Console.WriteLine("计算综采数据"+hSpan+"小时加权平均值");
            string sql = @"Procedure_ZC_Pretreat_JQ";            
            Db.ExecuteSP(sql, new { timeStart = tStart, timeEnd=tEnd, hSpan=hSpan});
        }
    }
}
